home *** CD-ROM | disk | FTP | other *** search
- Subject: v17i090: Record interactive session (using pipes)
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Kent Forschmiedt <happym!kent>
- Posting-number: Volume 17, Issue 90
- Archive-name: cscript
-
- [ This is like the UCB "script" program except it uses pipes,
- not psuedo-tty's. Some things break when run underneath it,
- but it's still worthwhile. I wrote the Makefile. --r$ ]
-
- This is a very generic script recorder. It works fine on most any Unix
- system. I think I got the original from Unix/World magazine, and I made
- it work a lot better and gave it a man page.
-
- I don't know if one like this has been posted before.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: Makefile cscript.1 cscript.c
- # Wrapped by rsalz@fig.bbn.com on Wed Feb 8 17:23:59 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(146 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#
- X# Makefile for cscript
- X#
- Xall: cscript
- X
- Xcscript: cscript.c
- X $(CC) -o cscript $(CFLAGS) cscript.c
- X
- Xman: cscript.1
- X nroff -man cscript.1 |col >man
- END_OF_FILE
- if test 146 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'cscript.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cscript.1'\"
- else
- echo shar: Extracting \"'cscript.1'\" \(1439 characters\)
- sed "s/^X//" >'cscript.1' <<'END_OF_FILE'
- X.TH CSCRIPT 1l
- X.SH NAME
- Xcscript \- record a terminal session
- X.SH SYNOPSIS
- X.B cscript [ \-aq ] [ \-s
- X.I shell
- X.B ] [
- X.I file
- X.B ]
- X.SH DESCRIPTION
- X.I Cscript
- Xrecords an interactive session in a file as it appears on the tty.
- X.PP
- XIf
- X.I file
- Xis specified, the script is recorded in
- X.I file.
- XOtherwise, the session is recorded in
- X.B typescript
- Xin the current directory.
- XThe
- X.B \-s
- Xoption causes
- X.I shell
- Xto be used instead of that specified by the
- X.B SHELL
- Xenvironment variable. If
- X.B SHELL
- Xis not defined, the default is
- X.B /bin/sh.
- XOther options and their actions are:
- X.TP "\w'\-a\ \ 'u"
- X.B \-a
- XAppend to the script file. Otherwise, the file is truncated.
- X.TP
- X.B \-q
- XQuiet mode. Don't print the time and date at the beginning and
- Xend of the script.
- X.PD
- X.PP
- X.SH FILES
- X.cc x
- X./typescript
- Xxcc
- X.SH SEE ALSO
- Xsh(1), csh(1), ksh(1) or whatever you use.
- X.SH DIAGNOSTICS
- XVarious complaints when \fIopen\fR(2), \fIfork\fR(2), \fIexec\fR(2),
- Xor \fIpipe\fR(2) calls fail.
- X.SH BUGS
- XUser input and program output are intercepted by different processes;
- Xthey might not appear in the same order in the script file as they did
- Xon the tty.
- X.PP
- XThis is a generic version, using only pipes. It should work on
- Xany reasonable imitation of Unix, but knows nothing about sockets,
- XStreams or ptys. Programs which care whether they are talking to
- Xa tty might not work right. Commands like \fIps\fR(1)
- Xwhich care about process groups probably won't work right.
- END_OF_FILE
- if test 1439 -ne `wc -c <'cscript.1'`; then
- echo shar: \"'cscript.1'\" unpacked with wrong size!
- fi
- # end of 'cscript.1'
- fi
- if test -f 'cscript.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cscript.c'\"
- else
- echo shar: Extracting \"'cscript.c'\" \(2905 characters\)
- sed "s/^X//" >'cscript.c' <<'END_OF_FILE'
- X/*
- X * cscript - record a terminal session
- X * Author: Grant Dorman
- X * Modified by Ray Swartz
- X * Modified by Kent Forschmiedt 20jun88
- X */
- X#ifndef lint
- Xstatic char *sccsid = "@(#)cscript.c 2.2 6/20/88";
- X#endif
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <fcntl.h>
- X
- X#define SHELL "/bin/sh"
- X#define SCRIPTOUT "typescript"
- X#define SHFLAGS "-i"
- X
- Xvoid exit(), perror();
- X
- Xchar *getenv(), *ctime();
- X
- Xint fd; /* record file */
- Xchar buf[BUFSIZ];
- Xchar *fname;
- Xchar *shell;
- Xint qflg;
- Xint ipd[2], opd[2]; /* pipes */
- X
- Xmain(argc, argv)
- Xint argc; char **argv;
- X{
- X int getopt();
- X extern char *optarg;
- X extern int optind;
- X
- X int c, oflags;
- X
- X oflags = O_WRONLY + O_CREAT + O_TRUNC;
- X shell = (char *)0;
- X
- X while ((c = getopt(argc, argv, "aqs:")) != EOF)
- X switch(c) {
- X case 'a': /* append mode */
- X oflags = O_WRONLY + O_CREAT + O_APPEND;
- X break;
- X case 'q': /* quiet mode */
- X qflg++;
- X break;
- X case 's':
- X shell = optarg;
- X break;
- X default:
- X fprintf(stderr, "Usage: cscript [-aq] [ -s shell ] [file]\n");
- X exit(3);
- X }
- X
- X if (!shell && (shell = getenv("SHELL")) == (char *)0)
- X shell = SHELL;
- X
- X fname = (optind < argc) ? argv[optind] : SCRIPTOUT;
- X if ( (fd = open(fname, oflags, 0666)) < 0) {
- X perror("cscript: open");
- X exit(4);
- X }
- X
- X if (pipe(ipd) == -1) {
- X perror("cscript: pipe");
- X exit(2);
- X }
- X if (pipe(opd) == -1) {
- X perror("cscript: pipe");
- X exit(2);
- X }
- X
- X switch(fork()) {
- X case -1: perror("cscript: fork 1"); exit(1);
- X
- X case 0: switch(fork()) {
- X case -1: perror("cscript: fork 2"); exit(1);
- X
- X case 0: do_stdin(); exit(6);
- X default: do_shell(); exit(6);
- X }
- X default: do_stdout(); exit(6);
- X }
- X
- X /* NOTREACHED */
- X}
- X
- X
- Xdo_stdout()
- X{
- X unsigned nread;
- X long time(), tloc;
- X
- X /* this process will exit when the pipe closes */
- X signal(SIGHUP, SIG_IGN); /* */
- X signal(SIGINT, SIG_IGN); /* */
- X signal(SIGQUIT, SIG_IGN); /* */
- X
- X close(ipd[0]); close(ipd[1]);
- X
- X close(0); dup(opd[0]);
- X close(opd[0]); close(opd[1]);
- X
- X fprintf(stderr, "Recording...\nExit shell to stop\n");
- X
- X while((nread = read(0, buf, sizeof buf)) != 0) {
- X write(1, buf, nread);
- X write(fd, buf, nread);
- X }
- X
- X if (!qflg) {
- X time(&tloc);
- X fprintf(stderr, "Script done, file is %s\n", fname);
- X sprintf(buf, "\nScript done %s", ctime(&tloc));
- X write(fd, buf, (unsigned) strlen(buf));
- X }
- X
- X exit(0);
- X}
- X
- Xdo_stdin()
- X{
- X unsigned nread;
- X
- X close(opd[0]); close(opd[1]);
- X close(1); dup(ipd[1]);
- X close(ipd[0]); close(ipd[1]);
- X
- X while((nread = read(0, buf, sizeof buf)) != 0) {
- X write(fd, buf, nread);
- X write(1, buf, nread);
- X }
- X
- X exit(0);
- X}
- X
- Xdo_shell()
- X{
- X long time(), tloc;
- X
- X close(0); dup(ipd[0]);
- X close(1); dup(opd[1]);
- X /* mush stderr into stdout pipe */
- X close(2); dup(opd[1]);
- X
- X close(opd[0]); close(opd[1]);
- X close(ipd[0]); close(ipd[1]);
- X close(fd);
- X
- X if (!qflg) {
- X time(&tloc);
- X fprintf(stderr, "Script started %s", ctime(&tloc));
- X }
- X
- X execl(shell, shell, SHFLAGS, 0);
- X perror("cscript: execl");
- X exit(5);
- X}
- END_OF_FILE
- if test 2905 -ne `wc -c <'cscript.c'`; then
- echo shar: \"'cscript.c'\" unpacked with wrong size!
- fi
- # end of 'cscript.c'
- fi
- echo shar: End of shell archive.
- exit 0
-